<?php

/**
 * Project:     Miky: the PHP compiling template engine
 * File:        miky.class.php

/**
 * @package Miky
 */
class Miky
{

    private $variables = Array();
    private $objects = Array();
    private $functions = Array();
    private $template = '{{$template}}';

    public $left_delimiter = '{{';
    public $right_delimiter = '}}';
        
    function register_function($code, $function_name, & $object = null)
    {
        $this->functions[$code] = Array('object'=>$object, 'function'=>$function_name);
    }

    function assign($code, $value)
    {
        $this->variables[$code] = $value;
    }

    function register_object($object_name, & $object)
    {
        $this->variables[$object_name] = $object;
    }

    function ParseParameters($bufer)
    {
        $ret = Array();

        $html = '<?xml version="1.0" encoding="utf-8" ?><body %s />';
        $html = sprintf($html, $bufer);
        $dom = new DOMDocument();
        $dom->loadHTML($html);
        $tags = $dom->getElementsByTagName('body');
        //$tag = new ();
        //$attr = new DOMAttr();
        foreach($tags as $tag)
        {
            foreach($tag->attributes as $attr)
            {
                $aval = $attr->value;
                // $aval = iconv('UTF-8', 'ISO-8859-1', $aval);
                $ret[$attr->name] = $aval;
            }
        }
        return $ret;
    }

    public function fetch($template_name)
    {
        $template = $this->template;
        $this->template = $this->fetchEx($template);
        return $this->template;
    }

    private function fetchEx($template)
    {
        global $mikron;
        $ldq = preg_quote($this->left_delimiter, '~');
        $rdq = preg_quote($this->right_delimiter, '~');
        $need_loop = false;
        do
        {
            $match = null;
            $replace_lib = Array(); 
            /* fetch all special blocks */
            // $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
            // $search = "~{$ldq}\s*superliteral\s*{$rdq}(.*){$ldq}\s*/superliteral\s*{$rdq}~su";
            $search = "~{$ldq}superliteral\s*{$rdq}(.*){$ldq}/superliteral{$rdq}~s";
            preg_match_all($search, $template, $match,  PREG_SET_ORDER);

            foreach($match as $m)
            {
                $replace_lib[md5($m[0])] = $m[0];
            }
            arsort($replace_lib);
            foreach($replace_lib as $key => $item)
            {
                $template = str_replace($item, $key, $template);
            }

            $need_loop = false;
            $pattern = '#\{\{(.+)\}\}#Us';
            preg_match_all($pattern, $template, $out);
            if(count($out) < 1)
            {
                return $template;
            }
            $out = $out[0];
            foreach($out as $instruction)
            {
                $instruction = substr($instruction, 2);
                $instruction = substr($instruction, 0, strlen($instruction)-2);
                if(substr($instruction, 0, 1) == '$')
                {
                    $code = substr($instruction, 1);
                    $codes = explode(' ', $code);
                    $code = trim($codes[0]);
                    if(array_key_exists($code, $this->variables))
                    {
                        $value = $this->variables[$code];
                        if(!is_object($value))
                        {
                            $p = '{{'.$instruction.'}}';
                            $template = str_replace($p, $value, $template);
                            $need_loop = true;
                        }
                    }
                }
                else
                {
                    $p = '{{'.$instruction.'}}';
                    /*$pos = strpos($instruction, ' ');
                    if($pos !== false)
                    {
                        $instruction = '"'.substr($instruction, 0, $pos).'"'.substr($instruction, $pos);
                    }
                    else
                    {
                        $instruction = '"'.$instruction.'"';
                    }*/
                    $parameters = $this->ParseParameters('mikron_tag_name='.$instruction);
                    $op_name = $parameters['mikron_tag_name'];
                    unset($parameters['mikron_tag_name']);
                    if(array_key_exists($op_name, $this->functions))
                    {
                        $ins = $this->functions[$op_name];
                        $object = & $ins['object'];
                        $function_name = $ins['function'];
                        if(is_object($object))
                        {
                            $instruction_value = CatchFunction($function_name, $parameters, $object);
                        }
                        else
                        {
                            $instruction_value = CatchFunction($function_name, $parameters);
                        }
                        $template = str_replace($p, $instruction_value, $template);
                    }
                    else
                    {
                        $instruction_value = '<font color="red">Управляющей инструкции «'.$op_name.'» не назначена функция.</font>';
                        $template = str_replace($p, $instruction_value, $template);
                    }
                }
            }

            foreach($replace_lib as $key => $item)
            {
                $template = str_replace($key, $item, $template);
            }

        } while ($need_loop);
        return $template;
    }

}

?>
